package com.liliudong.cursormate.interceptor;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionInterceptor;
import com.liliudong.cursormate.common.constant.CursorMetaConst;
import com.liliudong.cursormate.common.constant.DataScopeTypeEnum;
import com.liliudong.cursormate.common.constant.SecurityConst;
import lombok.RequiredArgsConstructor;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.expression.operators.relational.LikeExpression;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.SelectExpressionItem;
import net.sf.jsqlparser.statement.select.SubSelect;

import java.util.Objects;

/**
 * 自定义数据权限拦截器
 *
 * @author liudo
 * @version 1.0
 * @project cursor-mate
 * @date 2023/10/27 20:04:24
 */
@RequiredArgsConstructor
public class CursorMateDataPermissionInterceptor extends DataPermissionInterceptor {

    private static final String ORG_NO_BY = "org_no_by";

    @Override
    protected void setWhere(PlainSelect plainSelect, String whereSegment) {
        // 没有登录则放行
        if (!StpUtil.isLogin()) {
            return;
        }
        Table table = (Table) plainSelect.getFromItem();
        String tableAliasName = Objects.nonNull(table.getAlias()) ? table.getAlias().getName() : null;

        Column tableColum;
        // 当前部门及部门以下权限
        Integer dataScope = Convert.toInt(StpUtil.getExtra(SecurityConst.DATA_SCOPE));
        String orgNo = Convert.toStr(StpUtil.getExtra(SecurityConst.ORG_NO));
        long userId = StpUtil.getLoginIdAsLong();
        if (Objects.equals(dataScope, DataScopeTypeEnum.OWN_AND_SUB_ORGANIZATION.getValue())) {
            tableColum = getColumn(tableAliasName, ORG_NO_BY);
            // 部门及部门以下权限，拼接 create_user_org_no like 'userOrgNo%'
            // 支持一个自定义条件
            LikeExpression likeExpression = new LikeExpression();
            likeExpression.setLeftExpression(tableColum);
            likeExpression.setRightExpression(new StringValue(orgNo + "%"));
            setWhereAnd(plainSelect, likeExpression);
        }
        if (Objects.equals(dataScope, DataScopeTypeEnum.OWN_ORGANIZATION.getValue())) {
            tableColum = getColumn(tableAliasName, ORG_NO_BY);
            // 部门权限，拼接 create_user_org_no = 'userOrgNo'
            EqualsTo equalsTo = new EqualsTo(tableColum, new StringValue(orgNo));
            setWhereAnd(plainSelect, equalsTo);
        }
        if (Objects.equals(dataScope, DataScopeTypeEnum.ONLY_OWN.getValue())) {
            // 仅自己权限，拼接 create_user_id = 'userId'
            Column createUserIdColumn = getColumn(tableAliasName, CursorMetaConst.CREATED_BY);
            EqualsTo equalsTo = new EqualsTo(createUserIdColumn,
                    new LongValue(userId));
            setWhereAnd(plainSelect, equalsTo);
        }
        // 自定义权限
        if (Objects.equals(dataScope, DataScopeTypeEnum.CUSTOM.getValue())) {
            tableColum = getColumn(tableAliasName, ORG_NO_BY);
            // 自定义权限 拼接 and org_no_by in ( select org_no from sys_user_scope where user_id = ?)
            PlainSelect sysUserScopeSelect = new PlainSelect();
            Table sysUserScope = new Table("sys_user_scope");
            SelectExpressionItem selectExpressionItem = new SelectExpressionItem();
            selectExpressionItem.setExpression(new Column(sysUserScope, "org_no"));
            EqualsTo equalsTo = new EqualsTo(new Column("user_id"), new LongValue(userId));
            sysUserScopeSelect.setFromItem(sysUserScope);
            sysUserScopeSelect.addSelectItems(selectExpressionItem);
            sysUserScopeSelect.setWhere(equalsTo);
            // 构建in查询
            InExpression inExpression = new InExpression();

            SubSelect subSelect1 = new SubSelect();
            subSelect1.setSelectBody(sysUserScopeSelect);

            inExpression.setRightItemsList(subSelect1);
            inExpression.setLeftExpression(tableColum);
            setWhereAnd(plainSelect, inExpression);
        }
    }

    private Column getColumn(String tableAliasName, String columnName) {
        if (StrUtil.isEmpty(tableAliasName)) {
            return new Column(columnName);
        } else {
            return new Column(tableAliasName + "." + columnName);
        }
    }

    private void setWhereAnd(PlainSelect plainSelect, Expression expression) {
        if (Objects.nonNull(expression)) {
            if (Objects.nonNull(plainSelect.getWhere())) {
                plainSelect.setWhere(new AndExpression(plainSelect.getWhere(), expression));
            } else {
                plainSelect.setWhere(expression);
            }
        }
    }

    private void setWhereOr(PlainSelect plainSelect, Expression expression) {
        if (Objects.nonNull(expression)) {
            if (Objects.nonNull(plainSelect.getWhere())) {
                plainSelect.setWhere(new OrExpression(plainSelect.getWhere(), new Parenthesis(expression)));
            } else {
                plainSelect.setWhere(expression);
            }
        }
    }
}
